package com.hb.trade.server.project.opening.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hb.core.pojo.enums.OpeningBidStatusEnum;
import com.hb.core.pojo.enums.SectionStatusEnum;
import com.hb.core.pojo.parent.PageResult;
import com.hb.core.pojo.project.opening.dto.OpeningBidTenderDTO;
import com.hb.core.pojo.project.opening.dto.OpeningBidTenderRecordDTO;
import com.hb.core.pojo.project.opening.entity.OpeningBidInfo;
import com.hb.core.pojo.project.opening.entity.OpeningBidTender;
import com.hb.core.pojo.project.opening.entity.OpeningSet;
import com.hb.core.pojo.project.opening.mapper.OpeningBidInfoMapper;
import com.hb.core.pojo.project.opening.mapper.OpeningBidTenderMapper;
import com.hb.core.pojo.project.opening.mapper.OpeningBidTenderRecordMapper;
import com.hb.core.pojo.project.section.dto.BidSectionDTO;
import com.hb.core.pojo.project.section.entity.BidSection;
import com.hb.trade.server.project.opening.service.OpeningBidHallService;
import com.hb.trade.server.project.opening.service.OpeningSetService;
import com.hb.trade.server.project.proj.service.ProjectService;
import com.hb.trade.server.project.section.service.raw.BidSectionService;
import com.hb.trade.server.project.section.service.raw.BidSectionTenderService;
import com.hb.trade.server.project.util.TextToAudioUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.fzzn.core.model.enums.LogicEnum;
import org.fzzn.core.util.Enums;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * 开标大厅实现类
 *
 * @author Lix1ang
 * @date 2021-11-24 11:20:33
 */
@Slf4j
@Service
public class OpeningBidHallServiceImpl extends ServiceImpl<OpeningBidInfoMapper, OpeningBidInfo> implements OpeningBidHallService {

    protected final OpeningBidTenderMapper openingBidTenderMapper;
    protected final BidSectionTenderService bidSectionTenderService;
    protected final BidSectionService bidSectionService;
    protected final OpeningSetService openingSetService;
    protected final ProjectService projectService;
    protected final OpeningBidTenderRecordMapper openingBidTenderRecordMapper;

    public OpeningBidHallServiceImpl(OpeningBidTenderMapper openingBidTenderMapper,
                                     BidSectionTenderService bidSectionTenderService,
                                     BidSectionService bidSectionService,
                                     OpeningSetService openingSetService,
                                     ProjectService projectService,
                                     OpeningBidTenderRecordMapper openingBidTenderRecordMapper) {
        this.openingBidTenderMapper = openingBidTenderMapper;
        this.bidSectionTenderService = bidSectionTenderService;
        this.bidSectionService = bidSectionService;
        this.openingSetService = openingSetService;
        this.projectService = projectService;
        this.openingBidTenderRecordMapper = openingBidTenderRecordMapper;
    }

    @Override
    public PageResult pageTodayBidOpeningSection(BidSectionDTO bidSectionDTO) {

        Page<BidSectionDTO> bidSectionDTOPage = baseMapper.pageTodayBidOpeningSection(
                bidSectionDTO.pages(), bidSectionDTO.getProjectId(),bidSectionDTO.getCreateId(),bidSectionDTO.getRoleSign(),bidSectionDTO.getOrgId());
        //处理标段状态showName
        for(BidSectionDTO bidSectionDTO1 : bidSectionDTOPage.getRecords()) {
            String openBidStatusName = Enums.nameOf(OpeningBidStatusEnum.class, bidSectionDTO1.getOpenBidStatus());
            bidSectionDTO1.setOpenBidStatusName(StrUtil.isEmpty(openBidStatusName) ? "未开标" : openBidStatusName);
            bidSectionDTO1.setOpenBidStatus(StrUtil.isEmpty(openBidStatusName) ? 0 : bidSectionDTO1.getOpenBidStatus());
        }
        return PageResult.get(bidSectionDTOPage);
    }

    @Override
    public List<BidSectionDTO> listTodayBidOpeningSection(BidSectionDTO bidSectionDTO) {

        List<BidSectionDTO> bidSectionDTOList = baseMapper.listTodayBidOpeningSection(bidSectionDTO.getProjectId(),bidSectionDTO.getCreateId(),bidSectionDTO.getRoleSign(),bidSectionDTO.getOrgId());
        if (CollUtil.isEmpty(bidSectionDTOList)){
            return bidSectionDTOList;
        }
        //处理标段状态showName
        for(BidSectionDTO bidSection : bidSectionDTOList) {
            String openBidStatusName = Enums.nameOf(OpeningBidStatusEnum.class, bidSection.getOpenBidStatus());
            bidSection.setOpenBidStatusName(StrUtil.isEmpty(openBidStatusName) ? "未开标" : openBidStatusName);
            bidSection.setOpenBidStatus(StrUtil.isEmpty(openBidStatusName) ? 0 : bidSection.getOpenBidStatus());
        }
        return bidSectionDTOList;
    }

    /**
     * 首页日期和企业ID查询参与的开标项目
     * @param bidSectionDTO
     * @return
     */
    @Override
    public PageResult pageTodayOpeningSection(BidSectionDTO bidSectionDTO) {
        Page<BidSectionDTO> bidSectionDTOPage;
        if (bidSectionDTO.getRoleSign() != null && bidSectionDTO.getRoleSign().equals(2)){
            bidSectionDTOPage = baseMapper.pageTodayOpeningSectionTender(
                    bidSectionDTO.pages(), bidSectionDTO);
        }else {
            bidSectionDTOPage = baseMapper.pageTodayOpeningSection(
                    bidSectionDTO.pages(), bidSectionDTO);
        }

        //处理标段状态showName
        LocalDateTime newDate = LocalDateTime.now();
        for(BidSectionDTO bidSectionDTO1 : bidSectionDTOPage.getRecords()) {
            // 获取开标截止时间（秒）
            Long endOpenBidTime = bidSectionDTO1.getOpenBidTime().isBefore(newDate)?0:newDate.until(bidSectionDTO1.getOpenBidTime(), ChronoUnit.SECONDS);;
            bidSectionDTO1.setEndOpenBidTime(endOpenBidTime);
            SectionStatusEnum sectionStatusEnum = SectionStatusEnum.getIns(bidSectionDTO1.getSectionStatus());
            if (sectionStatusEnum != null){
                bidSectionDTO1.setSectionStatusName(sectionStatusEnum.getShowName());
                bidSectionDTO1.setSectionStatusCode(sectionStatusEnum.getCode());
            }
        }
        return PageResult.get(bidSectionDTOPage);
    }

    @Override
    public List<OpeningBidTenderRecordDTO> listBidOpeningRecord(OpeningBidTender openingBidTender) {
        if (null == openingBidTender.getOpeningBidInfoId()) {
            return null;
        }
        List<OpeningBidTenderRecordDTO> tenderRecordDTOList = openingBidTenderMapper.listTenderRecord(openingBidTender);
        return tenderRecordDTOList;
    }

    @Override
    public List<OpeningBidTenderDTO> listBidOpeningTender(OpeningBidTender openingBidTender) {
        if (null == openingBidTender.getOpeningBidInfoId()) {
            return null;
        }
        List<OpeningBidTenderDTO> tenderDTOList = openingBidTenderMapper.listBidOpeningTender(openingBidTender);
        return tenderDTOList;
    }

    @Override
    @SneakyThrows
    public Map countHallInfo(Long id) {
        //查询开标大厅记录表
        OpeningBidInfo openingBidInfo = baseMapper.selectById(id);
        if (null == openingBidInfo) {
            log.warn("未获取到开标记录信息");
            return null;
        }
        //查询开标大厅供应商开标记录表
        List<OpeningBidTender> openingBidTenderList = openingBidTenderMapper.selectList(new LambdaQueryWrapper<OpeningBidTender>()
                .eq(OpeningBidTender :: getOpeningBidInfoId, openingBidInfo.getId()));

        //TODO 人数计算未完成，有效、无效人数没有相应字段过滤，或不确定关联哪个表数据，暂未处理
        int totalTenderNum = openingBidInfo.getBidSubmitCount();     //总投标人数
        int effectiveTenderNum = 0; //有效投标人数
        int invalidTenderNum = 0;   //无效投标人数
        int signedInTenderNum = 0;  //已签到人数
        int decryptedTenderNum = 0; //已解密人数

        for (OpeningBidTender openingBidTender : openingBidTenderList) {
            //判断此供应商是否签到
            if (openingBidTender.getSignFlag() == LogicEnum.YES.getCode()) {
                signedInTenderNum ++;
            }
            //判断此供应商是否解密
            if (openingBidTender.getDecryptFlag() == LogicEnum.YES.getCode()) {
                decryptedTenderNum ++;
            }
        }

        Map map = new HashMap();
        map.put("totalTenderNum", totalTenderNum);
        map.put("effectiveTenderNum", effectiveTenderNum);
        map.put("invalidTenderNum", invalidTenderNum);
        map.put("decryptedTenderNum", decryptedTenderNum);
        map.put("signedInTenderNum", signedInTenderNum);
        return map;
    }

    @Override
    public List<OpeningBidTender> listBidOpeningSchedule(OpeningBidInfo openingBidInfo) {
        if (null == openingBidInfo.getId()) {
            return null;
        }
        List<OpeningBidTender> openingBidTenderList = openingBidTenderMapper.selectList(new LambdaQueryWrapper<OpeningBidTender>()
                .eq(OpeningBidTender::getOpeningBidInfoId, openingBidInfo.getId())
                .eq(OpeningBidTender::getDecryptFlag, 1)
                .isNotNull(OpeningBidTender::getDecryptContent));

        // 因为还有别的方法引这个方法 noShow = 2 强制不隐藏报价信息
        if (CollUtil.isNotEmpty(openingBidTenderList) && null != openingBidInfo.getNoShow() && !openingBidInfo.getNoShow().equals(2)) {
            // 查询当前开标设置的人
            Long sectionId = openingBidTenderList.get(0).getSectionId();
            BidSection bidSection = bidSectionService.getById(sectionId);
            // 查询开标设置
            OpeningSet openingSet = openingSetService.getById(bidSection.getOpeningSetId());
            // 如果是不公开报价 需要将投标人的报价隐藏
            if (null != openingSet && openingSet.getOpenOfferType().equals(2)) {
                JSONConfig jsonConfig = new JSONConfig();
                jsonConfig.setOrder(true);
                // 如果当前访问的不是开标设置的人 则隐藏投标人报价
                if (!openingBidInfo.getCreateId().equals(openingSet.getCreateId()) || openingBidInfo.getNoShow().equals(3)) {
                    for (OpeningBidTender openingBidTender : openingBidTenderList) {
                        // 只看自己的报价
                        if(!openingBidTender.getBidderId().equals(openingBidInfo.getCreateId())){
                            //将唱标词转成JSONObject，遍历key，获取value，目的去除多余引号，解决音频文件播报有误
                            JSONObject decryptContentJSON = JSONUtil.parseObj(openingBidTender.getDecryptContent(), jsonConfig);

                            //decryptContentJSON.get("企业名称",String.class);
                            Iterator iter = decryptContentJSON.entrySet().iterator();
                            while (iter.hasNext()) {
                                Map.Entry entry = (Map.Entry) iter.next();
                                if (entry.getKey().toString().indexOf("投标报价") != -1 || entry.getKey().toString().indexOf("费率报价") != -1) {
                                    entry.setValue("******");
                                }
                            }
                            openingBidTender.setDecryptContent(decryptContentJSON.toString());
                        }
                    }
                }
            }
        }
        return openingBidTenderList;
    }

    @Override
    public void generateSingAudio(OpeningBidInfo openingBidInfo) {
        if (null == openingBidInfo.getSectionId()) {
            return;
        }
        openingBidInfo.setNoShow(3);
        //获取解密成功后的开标一览表信息
        List<OpeningBidTender> openingBidTenderList = listBidOpeningSchedule(openingBidInfo);
        //处理唱标词，生成音频文件
        StringBuilder singText = new StringBuilder();
        singText.append("下面开始唱标:");
        for (OpeningBidTender openingBidTender : openingBidTenderList) {
            String singContext = openingBidTender.getDecryptContent();
            JSONConfig jsonConfig = new JSONConfig();
            jsonConfig.setOrder(true);
            //将唱标词转成JSONObject，遍历key，获取value，目的去除多余引号，解决音频文件播报有误
            JSONObject jsonObject = JSONUtil.parseObj(singContext, jsonConfig);
            Set<String> keySet = jsonObject.keySet();
            for (String key : keySet) {
                // 如果是隐藏的开标信息则唱标不唱
                if (jsonObject.get(key).toString().indexOf("******") != -1) {
                    continue;
                }
                // 判断是否有单位
                boolean util = key.matches(".*（.*）.*");
                if (util) {
                    //判断单位中是否带有元、天
                    boolean moneyUtil = key.matches(".*（.*元）.*");
                    boolean dateUtil = key.matches(".*（天）.*");
                    //判断是否为数字
                    boolean numOrStr = jsonObject.get(key).toString().matches("\\d*");
                    boolean numOrStr1 = jsonObject.get(key).toString().matches("\\d*.\\d*");

                    //获取括号中的单位
                    Integer index = key.indexOf('（');
                    Integer last = key.indexOf('）');
                    String substring = key.substring(index + 1, last);
                    String strName = key.substring(0, index);
                    if (moneyUtil || dateUtil) {
                        if (numOrStr) {
                            // 纯数字
                            singText.append(strName).append("：").append(Long.parseLong(jsonObject.get(key).toString())).append(substring).append(",");
                        } else if (numOrStr1) {
                            // 带小数
                            singText.append(strName).append("：").append(Double.valueOf(jsonObject.get(key).toString())).append(substring).append(",");
                        } else {
                            if (key.indexOf("大写") != -1) {
                                // 大写默认信息带单位，所以生成的时候不带单位
                                singText.append(strName).append("：").append(jsonObject.get(key).toString()).append(",");
                            } else {
                                singText.append(strName).append("：").append(jsonObject.get(key).toString()).append(substring).append(",");
                            }
                        }
                    } else {
                        singText.append(strName).append("：").append(jsonObject.get(key).toString()).append(substring).append(",");
                    }

                } else {
                    singText.append(key + ":" + jsonObject.get(key) + ",");
                }
            }
        }
        log.info(singText.toString());
        try {
            TextToAudioUtil.convert(singText.toString(), openingBidInfo.getSectionId().toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public PageResult<OpeningBidTender> pageOpeningBidTender(Page<OpeningBidTender> page, Long sectionId, String orgName) {
        QueryWrapper<OpeningBidTender> wrapper = OpeningBidTender.wrapper();
        wrapper.eq("section_id",sectionId).like(StrUtil.isNotEmpty(orgName) ,"decrypt_content",orgName);

        openingBidTenderMapper.selectPage(page,wrapper);
        return PageResult.get(page);
    }
    /**
     *
     * @Description: 查询标段的中标金额
     * @Author: zhongdl
     * @Date:2022/2/7 9:01
     * @param sectionId: 标段id
     * @return: {@link BigDecimal }
     **/
    @Override
    public BigDecimal getWinAmount(Long sectionId,Long orgId) {
        QueryWrapper<OpeningBidTender> wrapper = OpeningBidTender.wrapper();
        wrapper.eq("section_id",sectionId).eq("org_id",orgId).last("limit 1");
        //查询标段的开标信息
        OpeningBidTender openingBidTender = openingBidTenderMapper.selectOne(wrapper);
        if (openingBidTender == null){
            return BigDecimal.ZERO;
        }

        String decryptContent = openingBidTender.getDecryptContent();
        if (StrUtil.isEmpty(decryptContent)){
            return BigDecimal.ZERO;
        }
        JSONObject jsonObject = JSONUtil.parseObj(decryptContent);
        if (jsonObject == null){
            return BigDecimal.ZERO;
        }
        BigDecimal bigDecimal = jsonObject.get("投标报价小写（元）", BigDecimal.class);
        return bigDecimal;
    }
}
